#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <jsoncpp/json/json.h>

#define SEP " "             // 分隔符
#define SEP_LEN strlen(SEP) // 分隔符长度
#define LINE_SEP "\r\n"     // 行结束标志
#define LINE_SEP_LEN strlen(LINE_SEP)

// enLength、deLength和Request、Response中的成员变量的选择，属于定制协议

// 给序列化后的字符串添加报头，"正文长度\r\n正文\r\n"
std::string enLength(std::string &text)
{
    std::string send_str = std::to_string(text.size()); // 字符串格式的正文长度
    send_str += LINE_SEP;
    send_str += text;
    send_str += LINE_SEP;
    return send_str;
}

// 去掉报头等，获取正文
bool deLength(std::string &str, std::string &text)
{
    auto pos = str.find(LINE_SEP);
    if (pos == std::string::npos)
        return false;
    std::string text_len_str = str.substr(0, pos); // 得到正文长度的字符串格式
    int text_len = std::stoi(text_len_str);        // 转为正文长度
    text = str.substr(pos + LINE_SEP_LEN, text_len);
    return true;
}

class Request
{
public:
    Request()
    {
    }
    Request(int x_, int y_, char op_)
        : x(x_), y(y_), op(op_)
    {
    }

    // 序列化，往外发
    bool serialize(std::string *out)
    {
#ifdef MYSELF
        //"x op y"
        *out = "";
        *out = std::to_string(x);
        *out += SEP;
        *out += op;
        *out += SEP;
        *out += std::to_string(y);
#else
        Json::Value root;
        root["first"] = x; // kv键值对的形式
        root["second"] = y;
        root["oper"] = op;

        Json::FastWriter w;
        *out = w.write(root);

#endif

        return true;
    }

    // 反序列化
    bool deserialize(std::string *in)
    {
#ifdef MYSELF
        //"x op y"
        auto left = in->find(SEP);
        auto right = in->rfind(SEP);
        if (left == std::string::npos || left == right)
            return false;
        if (right - left != 2)
            return false;

        std::string x_str = in->substr(0, left);
        std::string y_str = in->substr(right + SEP_LEN);
        x = std::stoi(x_str);
        y = std::stoi(y_str);
        op = (*in)[left + 1];
#else
        Json::Value root;
        Json::Reader r;
        r.parse(*in, root);

        x = root["first"].asInt();
        y = root["second"].asInt();
        op = root["oper"].asInt();

#endif
        return true;
    }

public:
    int x;
    int y;
    char op;
};

class Response
{
public:
    Response()
        : flag(0), result(0)
    {
    }
    Response(int flag_, int result_)
        : flag(flag_), result(result_)
    {
    }

    bool serialize(std::string *out)
    {
#ifdef MYSELF
        *out = "";
        *out = std::to_string(flag);
        *out += SEP;
        *out += std::to_string(result);

#else
        Json::Value root;
        Json::FastWriter w;
        root["flag"] = flag;
        root["result"] = result;

        *out = w.write(root);

#endif
        return true;
    }

    bool deserialize(std::string *in)
    {
#ifdef MYSELF
        auto pos = in->find(SEP);
        if (pos == std::string::npos)
            return false;

        std::string flag_str = in->substr(0, pos);
        std::string re_str = in->substr(pos + SEP_LEN);

        flag = std::stoi(flag_str);
        result = std::stoi(re_str);
#else
        Json::Value root;
        Json::Reader r;
        r.parse(*in, root);

        flag = root["flag"].asInt();
        result = root["result"].asInt();
#endif
    }

public:
    int flag;
    int result;
};

// inbuf是服务器接收缓冲区或客户端接收缓冲区，即把各自读到的数据放到inbuf中
//"text_len_str\r\ntext\r\n""text_len_str\r\ntext\r\n""text_len_str\r\ntext\r\n"
bool getOnePackage(std::string &inbuf, std::string &package)
{
    package = "";
    // char buf[1024];
    // while (1)
    // {
    //     int n = recv(sock, buf, sizeof(buf) - 1, 0);
    //     if (n > 0)
    //     {
    //         buf[n] = 0;
    //         inbuf += buf; // 把读到的数据放入接收缓冲区
    size_t pos = inbuf.find(LINE_SEP);
            if (pos == std::string::npos) // 如果接收缓冲区没有\r\n，说明还没读到一个完整的报文，继续读
                return false;
    std::string text_len_str = inbuf.substr(0, pos);
    int text_len = std::stoi(text_len_str);
    int total_len = text_len + 2 * LINE_SEP_LEN + text_len_str.size(); // 完整报文的长度
    if (inbuf.size() < total_len)
        return false;

    std::cout << "接收缓冲区，读取前:\n"
              << inbuf << std::endl;
    // 到此，至少有一个完整的报文
    package = inbuf.substr(0, total_len);
    inbuf.erase(0, total_len);

    return true;
}

